//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<data_loader.cpp>
///	@path	~/src/database/store/
///	@date	2008/04/16
///	@desc	.

#include "config/config.h"

#include "database/store/data_loader.h"

namespace xeres {

	namespace
	{
		// skip white space
		void _skip_ws( const wchar_t *& ptr )
		{
			while( *ptr && isspace( *ptr ) )
				++ptr;
		}

		void _next_token( const wchar_t *& ptr )
		{
			_skip_ws( ptr );
			if( *ptr == 0 )
				return;
			assert( *ptr == ',' );
			++ptr;
			_skip_ws( ptr );
		}

		// data taken function
		bool _take_data( int count , const wchar_t *& ptr , byte *& pbuffer )
		{
			_skip_ws( ptr );
			if( *ptr == 0 ) return false;

			if( count < 0 )
			{
				// means integer or color!
				count = -count; // fix

				for( int i = 0 ; i < count ; ++i )
				{
					if( *ptr == 0 ) return false;
					int val = xstrtoi_scan( ptr );
					memcpy( pbuffer , &val , sizeof(int) );
					pbuffer += sizeof(int);
					_next_token( ptr );
				}
			}
			else
			{
				// means float!
				for( int i = 0 ; i < count ; ++i )
				{
					if( *ptr == 0 ) return false;
					float val = (float)xstrtod_scan( ptr );
					memcpy( pbuffer , &val , sizeof(float) );
					pbuffer += sizeof(float);
					_next_token( ptr );
				}
			}
			return true;
		}
	}

	// ParseCData
	bool DataLoader::ParseCData( const std::vector<ClassID>& structure , size_t count , const WString& cdata , byte * buffer , size_t len )
	{
		size_t sz = 0;
		int * taken = (int*)alloca( sizeof(int) * structure.size() );

		// check all elements in structure
		for( size_t i = 0 , total = structure.size() ; i < total ; ++i )
		{
			switch( (int)structure[i] )
			{
			case INT_TYPE_CLASS_ID:		taken[i] = -1; break;
			case FLOAT_TYPE_CLASS_ID:	taken[i] = 1; break;
			case PAIR_TYPE_CLASS_ID:	taken[i] = 2; break;
			case VECTOR_TYPE_CLASS_ID:	taken[i] = 3; break;
			case COLOR_TYPE_CLASS_ID:	taken[i] = 3; break;
			case QUAT_TYPE_CLASS_ID:	taken[i] = 4; break;
			case MATRIX_TYPE_CLASS_ID:	taken[i] = 16; break;
			default:
				TRACE_ERROR( _S("DataLoader::ParseCData: Invalid structure type, only basic type can be parsed.") );
				return false;
			}
			sz += abs( taken[i] );
		}
		sz *= count;

		if( len < sz )
		{
			TRACE_ERROR( _S("DataLoader::ParseCData: Buffer size mismatch (desired %i , input %i).") , sz , len );
			return false;
		}

		// parse data
		const wchar_t * ptr = cdata.c_str();
		byte * pbuffer = buffer;
		size_t total = len;

		for( size_t i = 0 ; i < count ; ++i )
		{
			// every row in cdata
			for( size_t c = 0 , total = structure.size() ; c < total ; ++c )
			{
				if( !_take_data( taken[c] , ptr , pbuffer ) )
					return false;
			}
		}

		return true;
	}

} // namespace xeres
